/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.gbvbahia.vendas.modelos;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

/**
 * Entidade que representa um usuário logado, utilizada pelo Container,
 * GlassFish para validação de login e segurança de acesso aos beans e páginas
 * da aplicação.<br> Acesse:
 * http://www.hildeberto.com/2010/05/yasmim-security-part-1-user.html Para ver
 * um tutorial de como configurar a segurança no GlassFish.
 *
 * @author Guilherme
 * @since 2013/02/25
 */
@Entity
@Table(name = "user_account")
public class Usuario implements Serializable {

    /**
     * Login do usuário, o método de
     * br.com.gbvbahia.margem.beans.UsuarioFacade.getUsuarioId() é para retornar
     * esse valor referente ao usuário logado.<br> Único por usuário.<br> Não
     * utiliza sequence.<br> Não pode ser nulo.
     */
    @Id
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "user_id", length = 50)
    private String userId;
    /**
     * Senha criptografada utilizando: <br>Algoritmo: MD5 <br> Encoding:
     * Base64<br> Não pode ser nulo.
     */
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "pass", nullable = false, length = 50)
    private String pass;
    /**
     * Data que a senha foi alterada pela ultima vez.
     */
    @Temporal(TemporalType.DATE)
    @Column(name = "date_pass", nullable = false)
    private Date dataAlteracaoSenha = new Date();
    /**
     * Define se usuário está liberado para login.
     */
    @Basic(optional = false)
    @NotNull
    @Column(name = "blocked", nullable = false)
    private boolean blocked = false;
    /**
     * Email do usuário, recebe validação regex:<br>
     * [a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_` {|}~-]+)
     *
     * @(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.+[a-z0-9](?:
     * [a-z0-9-]*[a-z0-9])?<br> Não pode ser nulo.
     */
    @Pattern(regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`"
            + "{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:"
            + "[a-z0-9-]*[a-z0-9])?",
            message = "{email.invalido}")
    @Size(max = 100)
    @Column(name = "email", length = 100, unique = true)
    private String email;
    /**
     * Nome do usuário. Não pode ser nulo.
     */
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "first_name", nullable = false, length = 50)
    private String firstName;
    /**
     * Sobre nome do usuário. Não pode ser nulo.
     */
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "last_name", nullable = false, length = 50)
    private String lastName;
    /**
     * Não possui implementação atualmente, pode ser utilizado para criar código
     * de recuperação de senha.
     */
    @Size(max = 32)
    @Column(name = "confirmation_code", length = 32)
    private String confirmationCode;
    /**
     * Grupos aos quais o usuário está vinculado.<br> FetchType.EAGER<br>
     * Tabela Intermediária: user_group
     */
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_group",
            joinColumns = {
        @JoinColumn(name = "user_id",
                referencedColumnName = "user_id")},
            inverseJoinColumns =
            @JoinColumn(name = "grupo_id",
            referencedColumnName = "grupo_id"))
    private Set<Grupo> grupos;
    /**
     * Tentativas de login invalido.
     */
    @NotNull
    @Column(name = "user_tries", nullable = false)
    private Integer tries = 0;
    /**
     * Controle de transação otimista pela JPA.
     */
    @Version
    @Column(name = "version_manager", nullable = false)
    private Long version;
    /**
     * Telas
     */
    @Transient
    private boolean marcado;

    /**
     * Construtor Padrão.
     */
    public Usuario() {
    }

    /**
     * Define o login do usuário, não pode ser alterado após salvo no banco de
     * dados.
     *
     * @param userId java.lang.String.
     */
    public Usuario(final String userId) {
        this.userId = userId;
    }

    /**
     * Construtor com principais valores.
     *
     * @param userId
     * @param pass
     * @param blocked
     * @param firstName
     * @param lastName
     */
    public Usuario(final String userId, final String pass,
            final boolean blocked, final String firstName,
            final String lastName) {
        this.userId = userId;
        this.pass = pass;
        this.blocked = blocked;
        this.setFirstName(firstName);
        this.setLastName(lastName);
    }

    /**
     * Login do usuário.
     *
     * @return java.lang.String
     */
    public String getUserId() {
        return userId;
    }

    /**
     * Altera o login, se já estiver salvo no banco de dados esse valor não pode
     * ser alterado.
     *
     * @param userId java.lang.String
     */
    public void setUserId(String userId) {
        this.userId = userId;
    }

    /**
     * Senha criptografada do usuário. <br>Algoritmo: MD5 <br> Encoding:
     * Base64<br> Não pode ser nulo.
     *
     * @return java.lang.String
     */
    public String getPass() {
        return pass;
    }

    /**
     * Altera a senha do usuário. <br>Algoritmo: MD5 <br> Encoding: Base64<br>
     * Não pode ser nulo.
     *
     * @param pass
     */
    public void setPass(String pass) {
        this.pass = pass;
    }

    /**
     * Status usuário. <strong>Não implementado.</strong>
     *
     * @return boolean
     */
    public boolean getBlocked() {
        return blocked;
    }

    /**
     * Status usuário. <strong>Não implementado.</strong>
     *
     * @param blocked boolean
     */
    public void setBlocked(boolean blocked) {
        this.blocked = blocked;
    }

    /**
     * Email usuário.
     *
     * @return java.lang.String
     */
    public String getEmail() {
        return email;
    }

    /**
     * É validado por regex. Não pode ser nulo.
     *
     * @param email java.lang.String
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     * Nome usuário.<br> Não pode ser nulo.
     *
     * @return java.lang.String.
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * Altrera nome do usuário.<br> Nome pode ser null.
     *
     * @param firstName java.lang.String
     */
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     * Segundo nome usuário.
     *
     * @return java.lang.String
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * Segundo nome usuário. Não pode ser null.
     *
     * @param lastName java.lang.String
     */
    public void setLastName(String lastName) {
        this.lastName = (lastName);
    }

    /**
     * <strong>Não implementado.</strong>
     *
     * @return null
     */
    public String getConfirmationCode() {
        return confirmationCode;
    }

    /**
     * <strong>Não implementado.</strong>
     *
     * @param confirmationCode java.lang.String
     */
    public void setConfirmationCode(String confirmationCode) {
        this.confirmationCode = confirmationCode;
    }

    /**
     * Grupos que o usuário participa.<br> FetchType.EAGER
     *
     * @return java.util.Set&ltGrupo&gt
     */
    public Set<Grupo> getGrupos() {
        if (grupos == null) {
            grupos = new HashSet<Grupo>();
        }
        return grupos;
    }

    /**
     * Altera os grupos do usuário.
     *
     * @param grupos java.util.Set&ltGrupo&gt
     */
    public void setGrupos(Set<Grupo> grupos) {
        this.grupos = grupos;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (userId != null ? userId.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Usuario)) {
            return false;
        }
        Usuario other = (Usuario) object;
        if ((this.userId == null && other.userId != null) || (this.userId != null && !this.userId.equals(other.userId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "br.com.gbvbahia.margemmanager.modelos.Usuario[ userId="
                + userId + " ]";
    }

    public boolean isMarcadoTransient() {
        return marcado;
    }

    public void setMarcadoTransient(boolean marcadoTransient) {
        this.marcado = marcadoTransient;
    }

    public boolean verificarId() {
        return true;
    }

    public Serializable getId() {
        return this.getUserId();
    }

    public String getLabel() {
        return this.getUserId()
                + " : "
                + this.getFirstName()
                + " "
                + this.getLastName();
    }

    public Integer getTries() {
        return tries;
    }

    public void setTries(Integer tries) {
        this.tries = tries;
    }

    public Date getDataAlteracaoSenha() {
        return dataAlteracaoSenha;
    }

    public void setDataAlteracaoSenha(Date dataAlteracaoSenha) {
        this.dataAlteracaoSenha = dataAlteracaoSenha;
    }
}
